/**
  ******************************************************************************
  * @file    main.c 
  * @author  18408107475@163.com
  * @version V2.4.0
  * @date    2025-05-29
  * @brief   NM25Q128 Flash存储器测试程序
  * @details 
  * 硬件配置：
  *   - MCU: STM32F103ZET6 (72MHz Cortex-M3) 
  *     -> 采用ARM Cortex-M3内核，主频72MHz，512KB Flash，64KB SRAM
  *   - Flash: NM25Q128 (16MB NOR Flash)
  *     -> 存储容量：16MB (128Mbit)
  *     -> 组织结构：256字节/页，4096字节/扇区，65536字节/块
  *     -> 支持标准SPI接口（模式0/3）
  *   - SPI接口: SPI2 (PB13/PB14/PB15)
  *     -> PB13(SCK): 时钟线，最大频率104MHz
  *     -> PB14(MISO): 主设备输入从设备输出
  *     -> PB15(MOSI): 主设备输出从设备输入
  *   - 调试接口: USART1 (PA9/PA10, 115200bps)
  *     -> 8位数据位，无校验位，1位停止位
  * 
  * 软件特性：
  *   - 实现Flash芯片ID读取（JEDEC标准ID指令0x9F）
  *   - 支持扇区擦除(4KB)（指令0x20）
  *   - 支持页编程(256字节/页)（指令0x02）
  *   - 提供数据校验功能（回读比对）
  *   - 通过串口输出测试结果（用于调试验证）
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"          // STM32标准外设库（V3.5.0）
                                // 包含寄存器定义、位操作宏等
#include "Delay.h"              // 精确延时库（基于SysTick，±1us精度）
                                // 提供微秒级和毫秒级延时函数
#include "USART1_Config.h"      // 调试串口配置（PA9/PA10，8N1）
                                // 实现USART1初始化和数据收发
#include "NM25Q128_Config.h"    // Flash驱动（SPI2接口）
                                // 包含Flash指令定义和底层SPI操作

/* 变量定义 ------------------------------------------------------------------*/
u8 Sector_Write_Data[] = {0x01, 0x02, 0x03, 0x04}; // 测试数据模板
                                                    // 用于写入Flash的测试数据
u8 Read_Data[4];                                   // 数据读取缓冲区
                                                    // 存储从Flash读取的数据

/**
  ******************************************************************************
  * @brief  主程序入口
  * @param  None
  * @retval int 程序执行状态（实际不会返回）
  * @note   执行流程：
  *         1. 外设初始化（USART+SPI）
  *         2. 读取Flash芯片ID并输出
  *         3. 执行擦除-写入-读取验证测试
  *         4. 进入主循环
  ******************************************************************************
  */
int main(void)
{
    JEDEC_ID_t flashID; // Flash芯片ID存储结构体
                        // 包含Manufacturer_ID和Device_ID字段
    
    /* 第一阶段：硬件初始化 ------------------------------------------------*/
    USART1_Config(115200);  // 初始化调试串口
                            // - 使能USART1时钟
                            // - 配置GPIOA_Pin9/10为复用推挽输出
                            // - 波特率115200，8N1格式
                            
    NM25Q128_Init();        // 初始化Flash芯片
                            // - 使能SPI2时钟
                            // - 配置SPI2为主模式，8位数据格式
                            // - 设置时钟极性(CPOL)和相位(CPHA)
                            // - 片选引脚(GPIO)初始化
                            
    Delay_us(10);           // 等待电源稳定（tVSL）
                            // Flash芯片上电后需要的最小稳定时间

    /* 第二阶段：读取芯片ID ------------------------------------------------*/
    NM25Q128_ReadID(&flashID);  // 执行0x9F指令读取ID
                                // 时序：
                                // 1. 拉低片选
                                // 2. 发送0x9F指令码
                                // 3. 连续读取3字节（厂商ID+设备ID）
                                // 4. 拉高片选

    /* 通过串口输出芯片ID */
    USART1_SendByte(flashID.Manufacturer_ID);  // 发送厂商ID
                            // Winbond器件典型值为0x52
    USART1_SendByte(flashID.Device_ID >> 8);   // 发送设备ID高字节
                            // NM25Q128的设备ID高字节通常为0x20
    USART1_SendByte(flashID.Device_ID & 0xFF); // 发送设备ID低字节
                            // 设备ID低字节表示具体型号

    /* 第三阶段：Flash操作测试 --------------------------------------------*/
    // 擦除首扇区（地址0x000开始的4KB）
    NM25Q128_SectorErase(0x000);  
                            // 执行流程：
                            // 1. 发送写使能指令(0x06)
                            // 2. 发送扇区擦除指令(0x20)
                            // 3. 发送24位地址
                            // 4. 等待擦除完成（检查BUSY位）
    
    // 写入测试数据（地址0x000开始，写入4字节）
    NM25Q128_WritePage(0x000, Sector_Write_Data, 4);
                            // 执行流程：
                            // 1. 发送写使能指令(0x06)
                            // 2. 发送页编程指令(0x02)
                            // 3. 发送24位地址
                            // 4. 发送数据（不超过256字节）
                            // 5. 等待编程完成
    
    // 回读验证数据
    NM25Q128_ReadData(0x000, Read_Data, 4);
                            // 执行流程：
                            // 1. 发送读数据指令(0x03)
                            // 2. 发送24位地址
                            // 3. 连续读取数据
    
    NM25Q128_Sleep();       // 使Flash进入低功耗模式
                            // 发送0xB9指令，降低功耗
    
    // 发送读取结果到串口
    USART1_SendArray(Read_Data, 4);  
                            // 预期输出：0x01,0x02,0x03,0x04
                            // 若与写入数据一致，则验证通过

    /* 主循环（可根据需求添加功能） ----------------------------------------*/
    while(1)
    {
        // 典型扩展功能：
        // - 周期性读写测试
        // - Flash健康状况监测
        // - 通过串口接收指令进行交互式测试
    }
}

/************************ (C) COPYRIGHT 2025 Embedded Team *****END OF FILE****/
